import { TGALoader } from 'three/addons/loaders/TGALoader.js';
import { LoadingManager } from 'three/webgpu';

import { AddObjectCommand } from '../commands/AddObjectCommand.ts';
import type { Editor } from '../Editor.ts';
import LoaderUtils, { type TypeFileFlatMap } from './LoaderUtils.ts';
import { readFBXFile, readGLTFFile, readOBJFile, readPCDFile, readPLYFile, readSVGFile } from './utils.ts';

const REGEX_1 = /^(\.?\/)/; // test './'
const REGEX_2 = /\.tga$/i; // test tga file

class Loader {
  editor: Editor;
  texturePath: string;
  constructor(editor: Editor) {
    this.texturePath = '';
    this.editor = editor;
  }

  loadItemList = (items: DataTransferItemList) => {
    LoaderUtils.getFilesFromItemList(items, (files, filesMap) => {
      this.loadFiles(files, filesMap);
    });
  };

  loadFiles = (files: File[] | FileList, filesMap?: TypeFileFlatMap) => {
    const _files = Array.from(files);

    if (files.length > 0) {
      const _filesMap = filesMap || LoaderUtils.createFilesMap(_files);

      const manager = new LoadingManager();
      manager.setURLModifier((url) => {
        url = url.replace(REGEX_1, ''); // remove './'

        const file = _filesMap.get(url);

        if (file) {
          return URL.createObjectURL(file);
        }

        return url;
      });

      manager.addHandler(REGEX_2, new TGALoader());

      for (let i = 0; i < _files.length; i++) {
        this.loadFile(_files[i], manager);
      }
    }
  };

  loadFile = async (file: File, manager: LoadingManager) => {
    const editor = this.editor;
    const filename = file.name;
    const extension = filename.split('.').pop()?.toLowerCase();

    const reader = new FileReader();

    switch (extension) {
      case 'fbx': {
        readFBXFile(file, reader, manager).then((object) => {
          editor.execute(new AddObjectCommand(editor, object));
        });
        break;
      }

      case 'glb':
      case 'gltf': {
        const loader = LoaderUtils.createGLTFLoader(manager);
        editor.signals.rendererDetectKTX2Support.dispatch(loader.ktx2Loader);
        readGLTFFile(file, loader, reader).then((result) => {
          editor.execute(new AddObjectCommand(editor, result));
        });
        break;
      }

      case 'obj': {
        readOBJFile(file, reader).then((result) => {
          editor.execute(new AddObjectCommand(editor, result));
        });
        break;
      }

      case 'pcd': {
        readPCDFile(file, reader).then((result) => {
          editor.execute(new AddObjectCommand(editor, result));
        });
        break;
      }

      case 'ply': {
        readPLYFile(file, reader).then((result) => {
          editor.execute(new AddObjectCommand(editor, result));
        });
        break;
      }

      case 'svg': {
        readSVGFile(file, reader).then((group) => {
          editor.execute(new AddObjectCommand(editor, group));
        });
        break;
      }

      default:
        console.error(`Unsupported file format (${extension}).`);
        break;
    }
  };
}

export { Loader };
